﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace PspGameInfoReader
{
    public class PspGame
    {
        public string FileType { get; set; }
        public string FileVersion { get; set; }
        public int NameTableStartOffSet { get; set; }
        public int DataTableStartOffset { get; set; }
        public int NumOfVariables { get; set; }
        public List<string> DataValue { get; set; }
        public List<string> DataName { get; set; }

        private readonly List<byte[]> _type = new List<byte[]>();
        private readonly List<int> _usedSize = new List<int>();
        private readonly List<int> _blockSize = new List<int>();

        private static BinaryReader _reader;

        private const int FileNameOffset = 4;
        private const int FileVersionOffset = 4;
        private readonly byte[] number = new byte[] { 4, 4 };

        public PspGame()
        {
         
            DataValue = new List<string>();
            DataName = new List<string>();
        }

        public void BuildPspGame(string fileName)
        {
            _reader = new BinaryReader(File.Open(fileName, FileMode.Open));

            FileType = FileTypeFactory(FileNameOffset);
            FileVersion = FileVersionFactory(FileVersionOffset);
            NameTableStartOffSet = _reader.ReadInt32();
            DataTableStartOffset = _reader.ReadInt32();
            NumOfVariables = _reader.ReadInt32();

            for (int i = 0; i < NumOfVariables; i++)
            {
                _reader.BaseStream.Seek(2, SeekOrigin.Current);
                _type.Add(_reader.ReadBytes(2));
                _usedSize.Add(_reader.ReadInt32());
                _blockSize.Add(_reader.ReadInt32());
                _reader.BaseStream.Seek(4, SeekOrigin.Current);
            }

            _reader.BaseStream.Seek(NameTableStartOffSet, SeekOrigin.Begin);
            var names = _reader.ReadChars(DataTableStartOffset - NameTableStartOffSet);
            var data = new string(names);
            var datas = data.Split('\0');
             DataName.AddRange(datas);

            _reader.BaseStream.Seek(DataTableStartOffset, SeekOrigin.Begin);


            LoadData(NumOfVariables);
        }


        public void ShowResults()
        {
            Console.WriteLine("File Type = {0} ", FileType);
            Console.WriteLine("File Version = {0}", FileVersion);
            Console.WriteLine("Name Table Start Position = {0}", NameTableStartOffSet);
            Console.WriteLine("Name Table Start Position = {0}", DataTableStartOffset);

            for (int i = 0; i< NumOfVariables; i++)
            {
                Console.WriteLine("{0} = {1}", DataName[i], DataValue[i]);
            }

        }

        private static string FileTypeFactory(int fileNameOffset)
        {
            var result = _reader.ReadChars(fileNameOffset);
            return new String(result);
        }

        private static string FileVersionFactory(int fileVersionOffset)
        {
            var result = _reader.ReadBytes(fileVersionOffset);

            var stringBuilder = new StringBuilder();
            foreach (var value in result)
            {
                if (value != '\0')
                {
                    stringBuilder.Append((int)value).Append('.');
                }
            }
            return stringBuilder.ToString();
        }

        private void LoadData(int numOfVariables)
        {

            try
            {
                var dataValue = new List<byte[]>();

                for (int i = 0; i < numOfVariables; i++)
                {
                    var binaryData = _reader.ReadBytes(_blockSize[i]);
                    dataValue.Add(binaryData);

                    if (_type[i][0] == number[0] && _type[i][1] == number[1])
                    {
                        DataValue.Add(BitConverter.ToInt32(binaryData, 0).ToString());
                    }
                    else
                    {
                        DataValue.Add(Encoding.UTF8.GetString(binaryData,0, _usedSize[i]).TrimEnd('\0'));
                    }
                }
            }
            catch (Exception ex)
            {
            }
        
        }
    }
}
        
     

            



      

   


